package com.yc.framework.listener;

import com.github.benmanes.caffeine.cache.Cache;
import com.yc.common.constant.TokenConstants;
import com.yc.common.core.domain.model.LoginUser;
import com.yc.common.core.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.retry.support.RetryTemplate;

@Slf4j
public class TokenExpirationListener extends KeyExpirationEventMessageListener {

    private static final String ACCESS_PREFIX = TokenConstants.ACCESS_TOKEN_KEY;
    private static final String BACKUP_PREFIX = TokenConstants.BACKUP_PREFIX;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private Cache<String, LoginUser> tokenCache;

    @Autowired
    private RetryTemplate retryTemplate;

    public TokenExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    protected void doHandleMessage(Message message) {
        String expiredKey = message.toString();
        log.debug("接收到过期事件，key = {}", expiredKey);

        // 只处理 access_token 前缀的 key
        if (!expiredKey.startsWith(ACCESS_PREFIX)) {
            return;
        }

        // 使用 RetryTemplate 保证重试策略可配置
        retryTemplate.execute(context -> {
            String tokenId = expiredKey.substring(ACCESS_PREFIX.length());
            // 正确构建备份键名
            String backupKey = BACKUP_PREFIX + tokenId;

            // 从 Redis 备份中恢复用户信息
            LoginUser user = redisCache.getCacheObject(backupKey);
            if (user != null) {
                // 写入本地缓存
                tokenCache.put(tokenId, user);
                log.info("已将过期令牌 {} 的用户信息迁移到本地缓存", tokenId);
            } else {
                log.warn("未在备份找到令牌 {} 的用户信息", tokenId);
            }
            return null;
        });
    }
}